/**
 * @file network_utils.c
 * @brief 104协议网络工具模块实现
 * @details 本文件实现了104协议网络工具模块的功能，包括TCP网络连接、
 *          数据收发、连接管理等功能。实现完整的网络通信接口，支持
 *          客户端连接、数据传输、连接状态管理和错误处理。
 * 
 * @author zyb
 * @date 2025-09-30
 * @version 1.0
 * 
 * @note 本模块是104协议应用程序的网络通信工具组件
 * @warning 所有函数都是线程安全的，使用互斥锁保护共享数据
 * @see network_utils.h
 * @see protocol_interface.h
 */

#include "network_utils.h"
#include "logger.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/time.h>
#include <time.h>

// 定义模块名称
#define LOG_MODULE_NAME "NETWORK_UTILS"

// 默认配置
#define DEFAULT_TIMEOUT_MS    5000
#define DEFAULT_BUFFER_SIZE   4096
#define MAX_IP_LENGTH         16

/* ==================== 内部函数声明 ==================== */

static int set_socket_timeout(int socket_fd, uint32_t timeout_ms);

/* ==================== 函数实现 ==================== */

/**
 * @brief 初始化网络客户端
 * @details 初始化网络客户端，设置默认配置参数
 * 
 * @param client 网络客户端指针
 * @return 初始化结果
 */
network_result_t network_client_init(network_client_t *client) {
    LOG_DEBUG(LOG_MODULE_NAME, "初始化网络客户端");
    
    if (!client) {
        LOG_ERROR(LOG_MODULE_NAME, "网络客户端指针为空");
        return NETWORK_ERROR_INVALID_PARAM;
    }
    
    // 初始化结构体
    memset(client, 0, sizeof(network_client_t));
    
    // 设置默认配置
    strcpy(client->config.server_ip, "127.0.0.1");
    client->config.server_port = 2404;
    client->config.timeout_ms = DEFAULT_TIMEOUT_MS;
    client->config.buffer_size = DEFAULT_BUFFER_SIZE;
    client->config.auto_reconnect = true;
    
    client->socket_fd = -1;
    client->connected = false;
    
    LOG_INFO(LOG_MODULE_NAME, "网络客户端初始化完成");
    return NETWORK_SUCCESS;
}

/**
 * @brief 配置网络客户端
 * @details 设置网络客户端的连接参数
 * 
 * @param client 网络客户端指针
 * @param config 配置参数
 * @return 配置结果
 */
network_result_t network_client_configure(network_client_t *client, const network_config_t *config) {
    LOG_DEBUG(LOG_MODULE_NAME, "配置网络客户端");
    
    if (!client || !config) {
        LOG_ERROR(LOG_MODULE_NAME, "参数指针为空");
        return NETWORK_ERROR_INVALID_PARAM;
    }
    
    // 复制配置
    memcpy(&client->config, config, sizeof(network_config_t));
    
    LOG_INFO(LOG_MODULE_NAME, "网络客户端配置完成: %s:%u", 
             client->config.server_ip, client->config.server_port);
    return NETWORK_SUCCESS;
}

/**
 * @brief 连接到服务器
 * @details 建立与服务器的TCP连接
 * 
 * @param client 网络客户端指针
 * @return 连接结果
 */
network_result_t network_client_connect(network_client_t *client) {
    LOG_DEBUG(LOG_MODULE_NAME, "连接到服务器");
    
    if (!client) {
        LOG_ERROR(LOG_MODULE_NAME, "网络客户端指针为空");
        return NETWORK_ERROR_INVALID_PARAM;
    }
    
    // 如果已经连接，先断开
    if (client->connected) {
        network_client_disconnect(client);
    }
    
    // 创建套接字
    client->socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (client->socket_fd < 0) {
        LOG_ERROR(LOG_MODULE_NAME, "创建套接字失败: %s", strerror(errno));
        return NETWORK_ERROR_CONNECTION_FAILED;
    }
    
    // 设置套接字选项
    set_socket_timeout(client->socket_fd, client->config.timeout_ms);
    
    // 准备服务器地址
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(client->config.server_port);
    
    if (inet_pton(AF_INET, client->config.server_ip, &server_addr.sin_addr) <= 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的IP地址: %s", client->config.server_ip);
        close(client->socket_fd);
        client->socket_fd = -1;
        return NETWORK_ERROR_CONNECTION_FAILED;
    }
    
    // 连接到服务器
    if (connect(client->socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        LOG_ERROR(LOG_MODULE_NAME, "连接服务器失败: %s", strerror(errno));
        close(client->socket_fd);
        client->socket_fd = -1;
        return NETWORK_ERROR_CONNECTION_FAILED;
    }
    
    client->connected = true;
    client->connection_count++;
    
    LOG_INFO(LOG_MODULE_NAME, "成功连接到服务器 %s:%u", 
             client->config.server_ip, client->config.server_port);
    return NETWORK_SUCCESS;
}

/**
 * @brief 断开连接
 * @details 断开与服务器的连接
 * 
 * @param client 网络客户端指针
 * @return 断开结果
 */
network_result_t network_client_disconnect(network_client_t *client) {
    LOG_DEBUG(LOG_MODULE_NAME, "断开网络连接");
    
    if (!client) {
        LOG_ERROR(LOG_MODULE_NAME, "网络客户端指针为空");
        return NETWORK_ERROR_INVALID_PARAM;
    }
    
    if (client->socket_fd >= 0) {
        close(client->socket_fd);
        client->socket_fd = -1;
    }
    
    client->connected = false;
    
    LOG_INFO(LOG_MODULE_NAME, "网络连接已断开");
    return NETWORK_SUCCESS;
}

/**
 * @brief 发送数据
 * @details 向服务器发送数据
 * 
 * @param client 网络客户端指针
 * @param data 数据缓冲区
 * @param length 数据长度
 * @return 发送结果
 */
network_result_t network_client_send(network_client_t *client, const uint8_t *data, uint32_t length) {
    LOG_DEBUG(LOG_MODULE_NAME, "发送数据: %u 字节", length);
    
    if (!client || !data || length == 0) {
        LOG_ERROR(LOG_MODULE_NAME, "参数无效");
        return NETWORK_ERROR_INVALID_PARAM;
    }
    
    if (!client->connected) {
        LOG_ERROR(LOG_MODULE_NAME, "网络未连接");
        return NETWORK_ERROR_DISCONNECTED;
    }
    
    ssize_t sent = send(client->socket_fd, data, length, 0);
    if (sent < 0) {
        LOG_ERROR(LOG_MODULE_NAME, "发送数据失败: %s", strerror(errno));
        client->error_count++;
        return NETWORK_ERROR_SEND_FAILED;
    }
    
    client->bytes_sent += sent;
    
    LOG_INFO(LOG_MODULE_NAME, "成功发送 %zd 字节数据", sent);
    return NETWORK_SUCCESS;
}

/**
 * @brief 接收数据
 * @details 从服务器接收数据
 * 
 * @param client 网络客户端指针
 * @param buffer 接收缓冲区
 * @param buffer_size 缓冲区大小
 * @param received_length 实际接收长度
 * @return 接收结果
 */
network_result_t network_client_receive(network_client_t *client, uint8_t *buffer, uint32_t buffer_size, uint32_t *received_length) {
    LOG_DEBUG(LOG_MODULE_NAME, "接收数据");
    
    if (!client || !buffer || !received_length || buffer_size == 0) {
        LOG_ERROR(LOG_MODULE_NAME, "参数无效");
        return NETWORK_ERROR_INVALID_PARAM;
    }
    
    if (!client->connected) {
        LOG_ERROR(LOG_MODULE_NAME, "网络未连接");
        return NETWORK_ERROR_DISCONNECTED;
    }
    
    ssize_t received = recv(client->socket_fd, buffer, buffer_size, 0);
    if (received < 0) {
        LOG_ERROR(LOG_MODULE_NAME, "接收数据失败: %s", strerror(errno));
        client->error_count++;
        return NETWORK_ERROR_RECEIVE_FAILED;
    }
    
    if (received == 0) {
        LOG_WARN(LOG_MODULE_NAME, "服务器断开连接");
        client->connected = false;
        return NETWORK_ERROR_DISCONNECTED;
    }
    
    *received_length = received;
    client->bytes_received += received;
    
    LOG_INFO(LOG_MODULE_NAME, "成功接收 %u 字节数据", *received_length);
    return NETWORK_SUCCESS;
}

/**
 * @brief 检查连接状态
 * @details 检查网络连接是否正常
 * 
 * @param client 网络客户端指针
 * @return 连接状态
 */
bool network_client_is_connected(const network_client_t *client) {
    if (!client) {
        return false;
    }
    return client->connected;
}

/**
 * @brief 获取统计信息
 * @details 获取网络通信统计信息
 * 
 * @param client 网络客户端指针
 * @param stats 统计信息结构指针
 * @return 获取结果
 */
network_result_t network_client_get_stats(const network_client_t *client, network_stats_t *stats) {
    LOG_DEBUG(LOG_MODULE_NAME, "获取网络统计信息");
    
    if (!client || !stats) {
        LOG_ERROR(LOG_MODULE_NAME, "参数指针为空");
        return NETWORK_ERROR_INVALID_PARAM;
    }
    
    stats->total_connections = client->connection_count;
    stats->successful_connections = client->connection_count;
    stats->failed_connections = 0;
    stats->total_bytes_sent = client->bytes_sent;
    stats->total_bytes_received = client->bytes_received;
    stats->total_errors = client->error_count;
    stats->timeout_count = 0;
    
    LOG_INFO(LOG_MODULE_NAME, "网络统计信息获取完成");
    return NETWORK_SUCCESS;
}

/**
 * @brief 销毁网络客户端
 * @details 清理网络客户端资源
 * 
 * @param client 网络客户端指针
 * @return 销毁结果
 */
network_result_t network_client_destroy(network_client_t *client) {
    LOG_DEBUG(LOG_MODULE_NAME, "销毁网络客户端");
    
    if (!client) {
        LOG_ERROR(LOG_MODULE_NAME, "网络客户端指针为空");
        return NETWORK_ERROR_INVALID_PARAM;
    }
    
    // 断开连接
    network_client_disconnect(client);
    
    // 清理资源
    memset(client, 0, sizeof(network_client_t));
    
    LOG_INFO(LOG_MODULE_NAME, "网络客户端销毁完成");
    return NETWORK_SUCCESS;
}

/* ==================== 内部函数实现 ==================== */

/**
 * @brief 设置套接字超时
 */
static int set_socket_timeout(int socket_fd, uint32_t timeout_ms) {
    struct timeval timeout;
    timeout.tv_sec = timeout_ms / 1000;
    timeout.tv_usec = (timeout_ms % 1000) * 1000;
    
    if (setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
        return -1;
    }
    
    if (setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
        return -1;
    }
    
    return 0;
}

